home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
library
/
queue.lzh
/
queue
/
queue_library.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-18
|
9KB
|
405 lines
/*
queue_library.c --- queue library interface.
(c) Copyright 1995 SHW Wabnitz
Written by Bernhard Fastenrath (fasten@shw.com)
This file may be distributed under the terms
of the GNU General Public License.
*/
#if defined (__GNUC__)
#include <stabs.h>
#endif
#include "queue_library.h"
struct ExecBase *SysBase = NULL;
struct DosLibrary *DOSBase = NULL;
struct Library *QueueBase = NULL;
struct List Queues;
ULONG ClientsListBusy = 0;
#if defined (__GNUC__)
const BYTE LibName[] = "queue.library";
const BYTE LibIdString[] = "$VER: queue.library 1.0 (10-10-95)";
const UWORD LibVersion = 1;
const UWORD LibRevision = 0;
#endif
#if defined (__GNUC__)
#define LIBRT
#define REG(regname)
#define STRUCT_MYLIB struct Library
#else
#define LIBRT __saveds __asm
#define REG(reg-name) register __regname
#define ADDTABL_1(name,arg1);
#define ADDTABL_2(name,arg1,arg2);
#define ADDTABL_3(name,arg1,arg2,arg3);
#define ADDTABL_END();
#define STRUCT_MYLIB struct MyLibrary
#endif
/*** internal functions ***/
static ULONG
strlen (char *name)
{
ULONG t = 0;
while (name[t])
t++;
return t;
}
static void
RemoveAndReply (QMessage *msg)
{
QueueHandle *qh;
if (!msg -> qm_Refs)
{
qh = (QueueHandle *) msg -> qm_Owner;
Remove ((Node *) msg);
/*** reply to owner ***/
Forbid ();
AddHead (&qh -> qh_un.qhs.qhs_ReplyList, (Node *) msg);
Signal (qh -> qh_SigTask, qh -> qh_SigMask);
Permit ();
}
else
msg -> qm_Status = QMS_REMOVED;
}
static void
ReplyQMessage (QueueNode *qn, QMessage *msg)
{
msg -> qm_Refs --;
msg -> qm_Replies ++;
if (msg -> qm_Replies >= qn -> qn_Read || msg -> qm_Status == QMS_REMOVED)
RemoveAndReply (msg);
}
static void
cleanup (void)
{
if (DOSBase)
CloseLibrary ((struct Library *) DOSBase);
DOSBase = NULL;
}
/*** library interface ***/
int LIBRT
__UserLibInit (REG(a6) STRUCT_MYLIB *libbase)
{
SysBase = *(struct ExecBase **)4;
QueueBase = (struct Library *) libbase;
if (!(DOSBase = (struct DosLibrary *) OpenLibrary ("dos.library", 37)))
return 1;
NewList (&Queues);
return 0; /* success */
}
void LIBRT
__UserLibCleanup (REG(a6) STRUCT_MYLIB *libbase)
{
cleanup ();
}
ADDTABL_3(LIBQOpen,a0,d0,d1);
QHandle LIBRT
LIBQOpen (REG(a0) STRPTR name, REG(d0) ULONG mode, REG(d1) ULONG sigbit)
{
QueueHandle *qh;
QueueNode *qn;
ULONG len;
if (!(qh = (QueueHandle *) AllocMem (sizeof (QueueHandle), MEMF_PUBLIC | MEMF_CLEAR)))
return NULL;
Forbid ();
if (!(qn = (QueueNode *) FindName (&Queues, name)))
{
if (!(qn = AllocMem (sizeof (QueueNode), MEMF_PUBLIC | MEMF_CLEAR)))
{
FreeMem (qh, sizeof (QueueHandle));
Permit ();
return NULL;
}
len = strlen (name) + 1;
if (!(qn -> qn_Node.ln_Name = AllocMem (len, MEMF_PUBLIC)))
{
FreeMem (qh, sizeof (QueueHandle));
FreeMem (qh, sizeof (QueueNode));
Permit ();
return NULL;
}
CopyMem (name, qn -> qn_Node.ln_Name, len);
AddHead (&Queues, (Node *) qn);
NewList (&qn -> qn_Handles);
NewList (&qn -> qn_List);
}
qn -> qn_Refs ++;
AddHead (&qn -> qn_Handles, (Node *) qh);
qh -> qh_Mode = mode;
qh -> qh_QNode = qn;
qh -> qh_SigMask = 1 << sigbit;
qh -> qh_SigTask = FindTask (0);
if (mode == QMODE_LISTEN)
{
qn -> qn_Read ++;
qh -> qh_un.qhl.qhl_Status = QMS_MARKER;
Signal (qh -> qh_SigTask, qh -> qh_SigMask);
}
else
{
NewList (&qh -> qh_un.qhs.qhs_ReplyList);
}
Permit ();
return (QHandle) qh;
}
ADDTABL_1(LIBQClose,a0);
ULONG LIBRT
LIBQClose (REG(a0) QHandle qhandle)
{
QueueNode *qn = ((QueueHandle *) qhandle) -> qh_QNode;
QueueHandle *qh = qhandle;
QMessage *cmsg, *msg, *next;
Forbid ();
if (qh -> qh_Mode == QMODE_SEND)
{
if (qh -> qh_un.qhs.qhs_MsgCount)
{
Permit ();
return qh -> qh_un.qhs.qhs_MsgCount;
}
}
else
{
if (cmsg = (QMessage *) qh -> qh_un.qhl.qhl_MinNode.mln_Succ)
{
Remove ((Node *) &qh -> qh_un.qhl.qhl_MinNode); /* Remove marker */
next = cmsg;
}
else
{
if (cmsg = qh -> qh_un.qhl.qhl_Message)
next = (QMessage *) cmsg -> qm_MinNode.mln_Pred;
}
if (cmsg)
{
for (msg = next; next = (QMessage *) msg -> qm_MinNode.mln_Pred;
msg = next)
{
/* Replies from the current task
don't count after QClose().
*/
if (msg -> qm_Status == QMS_ACTIVE)
msg -> qm_Replies --;
}
}
if (!cmsg)
cmsg = (QMessage *) qn -> qn_List.lh_Head;
for (msg = cmsg; next = (QMessage *) msg -> qm_MinNode.mln_Succ; msg = next)
{
/* These messages might be in the queue, waiting only
for the current task; let's give them a chance.
*/
if ((msg -> qm_Status == QMS_ACTIVE && msg -> qm_Replies >= qn -> qn_Read)
|| msg -> qm_Status == QMS_REMOVED)
{
RemoveAndReply (msg);
}
if (msg -> qm_Status == QMS_MARKER)
break;
}
qn -> qn_Read --;
}
Remove ((Node *) qhandle);
FreeMem (qhandle, sizeof (QueueHandle));
if (! -- qn -> qn_Refs)
{
Remove ((Node *) qn);
FreeMem (qn -> qn_Node.ln_Name, strlen (qn -> qn_Node.ln_Name) + 1);
FreeMem (qn, sizeof (QueueNode));
}
Permit ();
return 0;
}
ADDTABL_2(LIBQAddMsg,a0,a1);
void LIBRT
LIBQAddMsg (REG(a0) QHandle qhandle, REG(a1) QMessage *msg)
{
QueueNode *qn = ((QueueHandle *) qhandle) -> qh_QNode;
QueueHandle *qh = (QueueHandle *) qhandle;
msg -> qm_Owner = qhandle;
msg -> qm_Refs = 0;
msg -> qm_Replies = 0;
msg -> qm_Status = QMS_ACTIVE;
Forbid ();
AddTail (&qn -> qn_List, (Node *) msg);
qh -> qh_un.qhs.qhs_MsgCount ++;
if (qn -> qn_Read)
{
for (qh = (QueueHandle *) qn -> qn_Handles.lh_Head; qh -> qh_MinNode.mln_Succ;
qh = (QueueHandle *) qh -> qh_MinNode.mln_Succ)
{
if (qh -> qh_Mode == QMODE_LISTEN)
Signal (qh -> qh_SigTask, qh -> qh_SigMask);
}
}
else
RemoveAndReply (msg);
Permit ();
}
ADDTABL_2(LIBQRemMsg,a0,a1);
void LIBRT
LIBQRemMsg (REG(a0) QHandle qhandle, REG(a1) QMessage *msg)
{
QueueNode *qn = ((QueueHandle *) qhandle) -> qh_QNode;
Forbid ();
RemoveAndReply (msg);
Permit ();
}
ADDTABL_1(LIBQGetMsg,a0);
QMessage * LIBRT
LIBQGetMsg (REG(a0) QHandle qhandle)
{
QueueNode *qn = ((QueueHandle *) qhandle) -> qh_QNode;
QueueHandle *qh = (QueueHandle *) qhandle;
QMessage *msg, *next;
Forbid ();
/* A server ( QMODE_SEND ) retrieves a replied message */
if (qh -> qh_Mode == QMODE_SEND)
{
if (msg = (QMessage *) RemTail (&qh -> qh_un.qhs.qhs_ReplyList))
qh -> qh_un.qhs.qhs_MsgCount --;
Permit ();
return msg;
}
/* A client ( QMODE_LISTEN ) reads a message */
if (msg = qh -> qh_un.qhl.qhl_Message)
{
/* automagically reply the current message */
next = (QMessage *) msg -> qm_MinNode.mln_Succ;
ReplyQMessage (qn, msg);
msg = next;
}
else /* no current message, start at marker or list head */
{
if (msg = (QMessage *) qh -> qh_un.qhl.qhl_MinNode.mln_Succ)
{
Remove ((Node *) &qh -> qh_un.qhl.qhl_MinNode);
qh -> qh_un.qhl.qhl_MinNode.mln_Succ = NULL;
}
else
msg = (QMessage *) qn -> qn_List.lh_Head;
}
for (;;)
{
if (!(next = (QMessage *) msg -> qm_MinNode.mln_Succ))
{
msg = NULL;
break;
}
if (msg -> qm_Status & QMS_INACTIVE)
{
if (msg -> qm_Status == QMS_REMOVED)
RemoveAndReply (msg);
msg = next;
continue;
}
msg -> qm_Refs ++;
break;
}
qh -> qh_un.qhl.qhl_Message = msg;
Permit ();
return msg;
}
ADDTABL_1(LIBQReplyMsg,a0);
ULONG LIBRT
LIBQReplyMsg (REG(a0) QHandle qhandle)
{
QueueNode *qn = ((QueueHandle *) qhandle) -> qh_QNode;
QueueHandle *qh = (QueueHandle *) qhandle;
QMessage *msg, *next;
if (!(msg = qh -> qh_un.qhl.qhl_Message))
return 0;
Forbid ();
/* Set marker */
if (qh -> qh_un.qhl.qhl_MinNode.mln_Succ)
Remove ((Node *) &qh -> qh_un.qhl.qhl_MinNode);
Insert (&qn -> qn_List, (Node *) &qh -> qh_un.qhl.qhl_MinNode, (Node *) msg);
next = (QMessage *) msg -> qm_MinNode.mln_Succ;
ReplyQMessage (qn, msg);
if (next)
{
for (msg = next; next = (QMessage *) msg -> qm_MinNode.mln_Succ; msg = next)
{
if (msg -> qm_Status == QMS_ACTIVE)
{
/* Since QReplyMsg() means you're not going to read more messages now
it's probably a good idea to remind you that there's more.
*/
Signal (qh -> qh_SigTask, qh -> qh_SigMask);
break;
}
}
}
qh -> qh_un.qhl.qhl_Message = NULL;
Permit ();
return 1;
}
ADDTABL_1(LIBQFlush,a0);
ULONG LIBRT
LIBQFlush (REG(a0) QHandle qhandle)
{
QueueNode *qn = ((QueueHandle *) qhandle) -> qh_QNode;
QMessage *msg, *next;
Forbid ();
msg = (QMessage *) qn -> qn_List.lh_Head;
while (next = (QMessage *) msg -> qm_MinNode.mln_Succ)
{
RemoveAndReply (msg);
msg = next;
}
Permit ();
return 1;
}
ADDTABL_END();